////////////////////////////////////////////////////////////////////////////////
//                                                                            //
//   Software       :                                                         //
//   Layer          : SRC                                                     //
//   Package        :                                                         //
//   Component      :                                                         //
//                                                                            //
//   File           : cdatabase.cxx                                           //
//   Author         : RSO ( Rafael Sotomayor Brûlé )                          //
//   EMail          : rsotomayor@savtec.cl                                    //
//   Type           : C++ Source                                              //
//   Usage          :                                                         //
//   Purpose        : gestión de usuario                                      //
//                                                                            //
//                                                                            //
//   who when        what                                                     //
//   ~~~ ~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
//   RSO 09-10-2010  Creation                                                 //
//                                                                            //
////////////////////////////////////////////////////////////////////////////////

#include "mylib/errlog.h"
#include "mylib/utilconf.h"
#include "cdatabase.h"
#include "cconfig.h"

#include <iostream>
using namespace std;

extern CGlobal *global_g;
extern CConfig *config_g;

CDataBase::CDataBase() {
  pthread_mutex_init (&mutDBMaestro_a, NULL); 
}

CDataBase::~CDataBase() {
  pthread_mutex_destroy (&mutDBMaestro_a); 
}



int CDataBase::initMaestros(string dbname_p) {
  sqlite3     *dbConn;  

  pthread_mutex_lock (&mutDBMaestro_a); 

  if ( sqlite3_open(dbname_p.data(), &dbConn) != SQLITE_OK) {
    errLog::LOGERR((errLog::SEVERE,(char*) "connect: Can't open the database %s in the file system\n",dbname_p.data(),sqlite3_errmsg(dbConn)));
    pthread_mutex_unlock (&mutDBMaestro_a);  
    return -1;
  }     

  int         rc ; 
  char        *zErrMsg = 0 ;
  string       sqlString;  

  string       sqlString_r[16];
  int          contador=0;

  sqlString = "CREATE TABLE IF NOT EXISTS sac_casinoalternativas \
      ( idalternativa     VARCHAR(20), \
        descripcion       VARCHAR(100), \
        fechahoraregistro DATETIME, \
        PRIMARY KEY  (idalternativa)  \
     ); ";
  sqlString_r[contador++] =  sqlString ;
  
  sqlString = "CREATE TABLE IF NOT EXISTS  sac_rolcasinoalternativa \
      ( \
      idrol              VARCHAR(20),  \
      idalternativa      VARCHAR(20), \
      maxticket          SMALLINT, \
      fechahoraregistro  DATETIME, \
      PRIMARY KEY  (idrol,idalternativa) \
      ); ";
  sqlString_r[contador++] =  sqlString ;

  sqlString = "CREATE TABLE IF NOT EXISTS  sac_roles ( \
      idrol               VARCHAR(20), \
      descripcion         VARCHAR(100), \
      fechahoraregistro   DATETIME, \
      PRIMARY KEY  (idrol)  \
      );";
  sqlString_r[contador++] =  sqlString ;

  sqlString = "CREATE TABLE  IF NOT EXISTS  sac_usuariorol \
        ( \
        idusuario             VARCHAR(20), \
        idrol                 VARCHAR(20), \
        fechahoraregistro     DATETIME, \
        PRIMARY KEY  (idusuario,idrol) \
        );" ;
  sqlString_r[contador++] =  sqlString ;

  sqlString = "CREATE TABLE IF NOT EXISTS sac_usuarios ( \
        idusuario             VARCHAR(20),   \
        apellidos             VARCHAR(100),  \
        nombres               VARCHAR(100),  \
        umbral                INTEGER, \
        opcionautentica       VARCHAR(45), \
        clave                 VARCHAR(45), \
        fecha_iniciocontrato  DATETIME, \
        fecha_terminocontrato DATETIME, \
        idorganizacion        VARCHAR(45), \
        imagen_contenido      BLOB, \
        imagen_tamano         INTEGER, \
        imagen_nombre         VARCHAR(100), \
        imagen_tipo           VARCHAR(100), \
        flagconfigura         SMALLINT, \
        fechahoraregistro     DATETIME, \
        PRIMARY KEY  (idusuario) \
    );" ; 

  sqlString_r[contador++] =  sqlString ;


  sqlString = "CREATE TABLE IF NOT EXISTS sac_transaccion ( \
      idusuario             VARCHAR(20), \
      ts                    TIMESTAMP, \
      idacceso              VARCHAR(45), \
      idmodulo              VARCHAR(45), \
      idmovil               VARCHAR(45), \
      latitud               REAL, \
      longitud              REAL, \
      altura                REAL, \
      velocidad             REAL, \
      rumbo                 REAL, \
      idestado              VARCHAR(45), \
      opcion                VARCHAR(45), \
      score                 INTEGER, \
      idevento              VARCHAR(45), \
      idtipoevento          VARCHAR(45), \
      idresultado           VARCHAR(45), \
      fechahoraregistro     DATETIME, \
      PRIMARY KEY  (idusuario,ts) \
      ); ";
  sqlString_r[contador++] =  sqlString ;


  sqlString = "CREATE INDEX IF NOT EXISTS idx_tr1 ON sac_transaccion (ts); ";
  sqlString_r[contador++] =  sqlString ;

  sqlString = "CREATE INDEX IF NOT EXISTS  idx_tr2  ON sac_transaccion (idusuario,ts); ";
  sqlString_r[contador++] =  sqlString ;
   
  sqlString = "CREATE INDEX IF NOT EXISTS  idx_tr3 ON sac_transaccion (idestado); ";
  sqlString_r[contador++] =  sqlString ;

  sqlString = "CREATE INDEX IF NOT EXISTS  idx_tr4 ON sac_transaccion (idevento); ";
  sqlString_r[contador++] =  sqlString ;

  sqlString = "CREATE TABLE IF NOT EXISTS  sac_usuariotemplate( \
        idusuario             VARCHAR(20), \
        idfinger              SMALLINT, \
        template1             BLOB, \
        templatesize1         INTEGER, \
        template2             BLOB, \
        templatesize2         INTEGER, \
        template3             BLOB, \
        templatesize3         INTEGER, \
        composite             BLOB, \
        nwidth                INTEGER, \
        nheight               INTEGER, \
        spoof                 INTEGER, \
        score                 INTEGER, \
        fechahora             DATETIME, \
        fechahoraregistro     DATETIME, \
        PRIMARY KEY  (idusuario,idfinger)  \
    );" ;
  sqlString_r[contador++] =  sqlString ;

  sqlString = "CREATE TABLE IF NOT EXISTS sac_usuariotarjeta   \
        (  \
            idtarjeta           VARCHAR(100),  \
            idusuario           VARCHAR(20),  \
            idestado            SMALLINT,  \
            fechahoraregistro   DATETIME, \
            PRIMARY KEY (idtarjeta)  \
        );" ; 
  sqlString_r[contador++] =  sqlString ;

  for ( int i=0; i < contador ; i++) {
    sqlString = sqlString_r[i] ;
    rc = sqlite3_exec(dbConn,sqlString.data(), NULL, 0, &zErrMsg);
    if( rc!=SQLITE_OK ){
      errLog::LOGERR((errLog::SEVERE, (char *)"Connect SQL error: %s:[ %s ]\n", zErrMsg,sqlString.data()));
      sqlite3_free(zErrMsg);
      sqlite3_close(dbConn);
      pthread_mutex_unlock (&mutDBMaestro_a);      
      return -1;
    }     
  }

  sqlite3_close(dbConn); 
  pthread_mutex_unlock (&mutDBMaestro_a);  
  return 0;
}



int CDataBase::insertaRegistroMarca(const char *idacceso_p,uint64_t idtarjeta_p,int idseleccion_p,time_t tStamp_p) {
  int retcode=-1;

  errLog::LOGERR((errLog::TRACE,"Stub insertaRegistroMarca\n"));

  return retcode ;

}

unsigned int CDataBase::getNumeroRegistros(string database_p,string tablename_p) {
  int rc;
  sqlite3    *dbConn;    
  sqlite3_stmt *stmt;
  
  int nregistrostotales=0;
  string sqlString ;

  pthread_mutex_lock (&mutDBMaestro_a); 

  sqlString  = "SELECT count(*) FROM " + tablename_p + "  ; " ;  
  
  if ( sqlite3_open(database_p.data(), &dbConn) != SQLITE_OK) {
    errLog::LOGERR((errLog::SEVERE, "connect: Can't open the database %s in the file system: %s\n",database_p.data(),sqlite3_errmsg(dbConn)));
    sqlite3_close(dbConn);
    pthread_mutex_unlock (&mutDBMaestro_a); 

    return -1;     
  }     
  
  rc = sqlite3_prepare(dbConn, sqlString.data(), -1, &stmt, 0);
  
  if ( rc != SQLITE_OK ) {
    errLog::LOGERR((errLog::SEVERE, "Error en sqlite3_prepare #%d: %s\n", rc, sqlite3_errmsg(dbConn)));
    sqlite3_close(dbConn);
    pthread_mutex_unlock (&mutDBMaestro_a); 
    return -1;         

  }

  int contadorIntentos = 0 ;
  while((rc = sqlite3_step(stmt)) != SQLITE_DONE) {
    if ( contadorIntentos++ > 10 ) {
      errLog::LOGERR((errLog::SEVERE, "Excede intentos sqlite3_step error #%d: %s\n", rc, sqlite3_errmsg(dbConn)));
      sqlite3_close(dbConn);
      pthread_mutex_unlock (&mutDBMaestro_a); 
      return -1;         
    } ;
    
    switch(rc) {
      case SQLITE_BUSY:
        errLog::LOGERR((errLog::WARN,"busy, wait 1 seconds\n"));
        sleep(1);
      break;
      case SQLITE_ERROR:
        errLog::LOGERR((errLog::WARN,"step error: %s\n", sqlite3_errmsg(dbConn)));
        break;
      case SQLITE_ROW:
        nregistrostotales  = sqlite3_column_int(stmt, 0);
        break;
    }
  }
  

  sqlite3_finalize(stmt);
  sqlite3_close(dbConn);
  pthread_mutex_unlock (&mutDBMaestro_a); 
  return nregistrostotales;
}

int CDataBase::eliminaRegistros(string database_p,string tablename_p) {
  int rc;
  sqlite3    *dbConn;    
  char        *zErrMsg = 0 ;

  string sqlString ;

  pthread_mutex_lock (&mutDBMaestro_a); 

  sqlString  = "DELETE FROM " + tablename_p + "  ; " ;  
  
  if ( sqlite3_open(database_p.data(), &dbConn) != SQLITE_OK) {
    errLog::LOGERR((errLog::SEVERE, "connect: Can't open the database %s in the file system: %s\n",database_p.data(),sqlite3_errmsg(dbConn)));
    sqlite3_close(dbConn);
    pthread_mutex_unlock (&mutDBMaestro_a); 
    return -1;     

  }     
  
  errLog::LOGERR((errLog::TRACE,(char *)"SQL: %s\n",sqlString.data()));

  rc = sqlite3_exec(dbConn,sqlString.data(), NULL, 0, &zErrMsg);
  if( rc!=SQLITE_OK ){
    errLog::LOGERR((errLog::SEVERE, (char *)"Connect SQL error: %s\n", zErrMsg));
    sqlite3_free(zErrMsg);
    sqlite3_close(dbConn);
    pthread_mutex_unlock (&mutDBMaestro_a); 
    return -1;         
  }

  sqlite3_close(dbConn);
  pthread_mutex_unlock (&mutDBMaestro_a); 

  return 0;
}

int CDataBase::guardarTransaccion(CGlobal::tTransaccion transaccion_p) {
  sqlite3     *dbConn;  
  int         rc ; 
  char        *zErrMsg = 0 ;
  string       sqlString;  


  errLog::LOGERR((errLog::TRACE,"Ingresa Transaccion %s en %s\n",transaccion_p.idusuario.data(),config_g->dbmaestros_a.data()));

  pthread_mutex_lock (&mutDBMaestro_a);

  if ( sqlite3_open(config_g->dbmaestros_a.data(), &dbConn) != SQLITE_OK) {
    errLog::LOGERR((errLog::SEVERE,(char*) "connect: Can't open the database %s in the file system\n",config_g->dbmaestros_a.data(),sqlite3_errmsg(dbConn)));
    sqlite3_close(dbConn);
    pthread_mutex_unlock (&mutDBMaestro_a);
    return -1 ;
  }   

  string strFechaHora ;
  getStringLocalTime(strFechaHora);

  char buffer[128] ;

  sqlString   = "INSERT INTO sac_transaccion(idusuario,ts,idacceso,idmodulo,idmovil,latitud,longitud,altura,velocidad,rumbo,idestado,opcion,score,idevento,idtipoevento,idresultado,fechahoraregistro) " ;
  sqlString  += "VALUES " ;
  sqlString  += "( " ;
  sqlString  += " '" + transaccion_p.idusuario + "'," ;
  sprintf(buffer,"%ld,",transaccion_p.geo.ts);
  sqlString  += buffer  ;
  sqlString  += " '" + transaccion_p.idacceso + "'," ;
  sqlString  += " '" + transaccion_p.idmodulo + "'," ;
  sqlString  += " '" + transaccion_p.idmovil + "', " ;
  sprintf(buffer,"%f,",transaccion_p.geo.latitud);
  sqlString  += buffer  ;
  sprintf(buffer,"%f,",transaccion_p.geo.longitud);
  sqlString  += buffer  ;
  sprintf(buffer,"%f,",transaccion_p.geo.altura);
  sqlString  += buffer  ;
  sprintf(buffer,"%f,",transaccion_p.geo.velocidad);
  sqlString  += buffer  ;
  sprintf(buffer,"%f,",transaccion_p.geo.rumbo);
  sqlString  += buffer  ;

  sqlString  += " '" + transaccion_p.idestado + "', " ;
  sqlString  += " '" + transaccion_p.opcion + "', " ;
  sprintf(buffer,"%d,",transaccion_p.score);
  sqlString  += buffer  ;

  sqlString  += " '" + transaccion_p.idevento + "', " ;
  sqlString  += " '" + transaccion_p.idtipoevento + "', " ;
  sqlString  += " '" + transaccion_p.idresultado + "', " ;
  sqlString  += " '" + strFechaHora + "' " ;
  sqlString  += " ) ; " ;

  errLog::LOGERR((errLog::TRACE,(char *)"SQL: %s\n",sqlString.data()));

  rc = sqlite3_exec(dbConn,sqlString.data(), NULL, 0, &zErrMsg);
  if( rc!=SQLITE_OK ){
    errLog::LOGERR((errLog::SEVERE, (char *)"Connect SQL error: %s\n", zErrMsg));
    sqlite3_free(zErrMsg);
    sqlite3_close(dbConn);
    pthread_mutex_unlock (&mutDBMaestro_a);
    return -1;         
  }

  sqlite3_close(dbConn);     
  pthread_mutex_unlock (&mutDBMaestro_a);
  errLog::LOGERR((errLog::INFO, "Ingresa Transaccion OK\n"));      

  return 0;

}



